package sk.lieskove.jianghongtiao.paris.helperutils.file;

import java.io.*;
import java.nio.channels.FileChannel;
import java.util.logging.Level;

/**
 * Convert persisted File to normal file
 *
 */
public class JavaFile2File 
{
    private static final Long FIFTY_MB = 52428800L;
    
    public static void main( String[] args ) throws FileNotFoundException, IllegalArgumentException, IOException
    {
        if(args.length != 2){
            throw new IllegalArgumentException("Only two parameters are allowed. Input and output file!");
        }
        File input = new File(args[0]);
        if(!input.exists()){
            throw new FileNotFoundException("Input file does not exists: "+input.getAbsolutePath());
        }
        File deserialize = (File) deserialize(input, File.class);
        doCopyFile(deserialize, new File(args[1]), true);
        //doCopyFile(deserialize, new File(args[1]), true);
    }
    

    /**
     * Internal copy file method.
     * 
     * @param srcFile  the validated source file, must not be <code>null</code>
     * @param destFile  the validated destination file, must not be <code>null</code>
     * @param preserveFileDate  whether to preserve the file date
     * @throws IOException if an error occurs
     */
    private static void doCopyFile(File srcFile, File destFile, boolean preserveFileDate) throws IOException {
        if (destFile.exists() && destFile.isDirectory()) {
            throw new IOException("Destination '" + destFile + "' exists but is a directory");
        }

        FileInputStream fis = null;
        FileOutputStream fos = null;
        FileChannel input = null;
        FileChannel output = null;
        try {
            fis = new FileInputStream(srcFile);
            fos = new FileOutputStream(destFile);
            input  = fis.getChannel();
            output = fos.getChannel();
            long size = input.size();
            long pos = 0;
            long count = 0;
            while (pos < size) {
                count = (size - pos) > FIFTY_MB ? FIFTY_MB : (size - pos);
                pos += output.transferFrom(input, pos, count);
            }
        } finally {
            closeQuietly(output);
            closeQuietly(fos);
            closeQuietly(input);
            closeQuietly(fis);
        }

        if (srcFile.length() != destFile.length()) {
            throw new IOException("Failed to copy full contents from '" +
                    srcFile + "' to '" + destFile + "'");
        }
        if (preserveFileDate) {
            destFile.setLastModified(srcFile.lastModified());
        }
    }

    private static void closeQuietly(Closeable closeable) {
        try {
            if (closeable != null) {
                closeable.close();
            }
        } catch (IOException ioe) {
            // ignore
        }
    }
    
    private static Object deserialize(File file, Class classType){
        Object output = null;
        FileInputStream fis = null;
        {
            ObjectInputStream ois = null;
            try {
                fis = new FileInputStream(file);
                ois = new ObjectInputStream(fis);
                output = classType.cast(ois.readObject());
            } catch (FileNotFoundException ex) {
               java.util.logging.Logger.getLogger(JavaFile2File.class.getName()).log(Level.SEVERE, null, ex);
            } catch (ClassNotFoundException ex) {
                java.util.logging.Logger.getLogger(JavaFile2File.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException ex) {
                java.util.logging.Logger.getLogger(JavaFile2File.class.getName()).log(Level.SEVERE, null, ex);
            } finally {
                try {
                    fis.close();
                } catch (IOException ex) {
                    java.util.logging.Logger.getLogger(JavaFile2File.class.getName()).log(Level.SEVERE, null, ex);
                }
                try {
                    ois.close();
                } catch (IOException ex) {
                    java.util.logging.Logger.getLogger(JavaFile2File.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return output;
    }
}
